﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SuperKit {
    public class HtmlConverter : CommandExecutor {
        public const string HEADER_TEMPLATE = "<!DOCTYPE html>\n<html>\n<head>\n<title>{0}</title>\n<meta charset = \"UTF-8\" >\n" +
            "<meta name= \"viewport\" content= \"width=device-width, initial-scale=1.0\" >\n</head>\n<body>\n<div>\n";
        public const string FOOT_TEMPLATE = "</div>\n</body>\n</html>";
        public const string CONTENT_TEMPLATE = "<LI><OBJECT type=\"text/sitemap\">\n" +
            "<param name = \"Name\" value=\"{0}\">\n<param name = \"Local\" value=\"{0}.html\"></OBJECT>\n";

        public const string CONTENT_HEADER = "<!DOCTYPE HTML PUBLIC \" -//IETF//DTD HTML//EN\">\n" +
            "< HTML >\n< HEAD >\n< meta name=\"GENERATOR\" content=\"Microsoft&reg; HTML Help Workshop 4.1\"><!-- Sitemap 1.0 -->\n</HEAD>" +
            "<BODY>\n<OBJECT type = \"text/site properties\" >\n\t< param name=\"ImageType\" value=\"Folder\">\n</OBJECT>\n<UL>\n";
        public const string CONTENT_FOOTER = "</UL>\n</ BODY ></ HTML >";

        public const string CHAPTER_HEADER = "\t<LI><OBJECT type=\"text/sitemap\">\n\t\t<param name = \"Name\" value=\"{0}\">\n\t\t</OBJECT>\n\t<UL>\n";
        public const string CHAPTER_FOOTER = "\n\t</UL>\n";
        public const string CHAPTER_ITEM = "\t\t<LI> <OBJECT type=\"text/sitemap\">\n" +
            "\t\t\t<param name = \"Name\" value=\"第{0}章\">\n\t\t\t<param name = \"Local\" value=\"{1}_{0}.html\">\n\t\t</OBJECT>\n";

        private StringBuilder sb = new StringBuilder(KFile.MB);
        private StringBuilder content = new StringBuilder(KFile.MB);
        private int SplitChapter { get; }
        private int SplitSize { get; }
        private int MaxChapter { get; }
        private int Current { get; set; }
        private int Count { get; set; }

        public HtmlConverter(ArgReader arg, IExecutorOwner form, string fpath) : base(arg, form, fpath) {
            SplitChapter = arg.GetInteger("-SplitChapter", 0);
            SplitSize = arg.GetInteger("-SplitSize", 0);
            MaxChapter = arg.GetInteger("-MaxChapter", 0);
        }

        public override void Execute() {
            Thread t = new Thread(ProcessThread);
            t.Start();
            
        }

        private void ProcessThread() {
            List<FileInfo> files = new List<FileInfo>();
            DirectoryInfo dir = new DirectoryInfo(FilePath);
            DirectoryEx.GetAllFiles(dir, files, new string[] { ".txt" });

            content.Append(CONTENT_HEADER);

            Count = files.Count;
            Current = 0;
            foreach (FileInfo file in files) {
                Current++;
                if (SplitChapter == 0 && SplitSize == 0) {
                    Process(file);
                } else {
                    ProcessChapter(file);
                }

            }

            content.Append(CONTENT_FOOTER);

            File.WriteAllText(Path.Combine(CreateTargetDir(), "Table of Contents.hhc"), content.ToString(), Encoding.UTF8);

            End();
        }

        private void ProcessChapter(FileInfo file) {
            var lines = KFile.ReadFileLines(file.FullName);
            var pureName = Path.GetFileNameWithoutExtension(file.Name);

            int chapter = GetChapterCount(file);
            if (chapter == 0) {
                chapter = 10;
                Flush("出现无法计算章节的文件({0}kb)：{1}", file.Length / 1024f, file.FullName);
            }

            var pageCount = lines.Count / chapter;

            int pointer = 0;
                       

            for (int i = 0; i < chapter; i++) {

                sb.Clear();
                sb.Append(string.Format(HEADER_TEMPLATE, string.Format("{0}_{1}", pureName, i + 1)));
                sb.Append(string.Format("<h1>{0} 第{1}卷</h1>", pureName, i + 1));

                

                for (int p = 0; p < pageCount; p++) {
                    if (pointer < lines.Count) {
                        sb.Append(string.Format("<p>{0}</p>\n", lines[pointer++]));
                    }                    
                }

                sb.Append(FOOT_TEMPLATE);

                string newPath = KFile.ReplaceExtension(GetTargetDirFile(file), ".html");
                newPath = KFile.AddSerialID(newPath, i + 1);
                SetStatus(string.Format("[{0}/{1}] - ({2}/{3}){4}", Current + 1, Count, i + 1, chapter, newPath));
                File.WriteAllText(newPath, sb.ToString(), Encoding.UTF8);
            }


            content.Append(string.Format(CHAPTER_HEADER, pureName));
            for (int i = 0; i < chapter; i++) {
                content.Append(string.Format(CHAPTER_ITEM, i + 1, pureName));
            }
            content.Append(CHAPTER_FOOTER);
            
        }

        private int GetChapterCount(FileInfo file) {
            int chapter = 0;
            try {
                if (SplitChapter != 0) {
                    chapter = SplitChapter;
                } else if (SplitSize != 0) {
                    chapter = (int)(file.Length / (KFile.KB * SplitSize));
                    if (chapter == 0) { // 小于指定KB
                        chapter = 1;
                    }
                }

                if (MaxChapter != 0 && chapter > MaxChapter) {
                    chapter = MaxChapter;
                }
            } catch {
                chapter = 10;
            }            


            return chapter;
        }

        private void Process(FileInfo file) {
            sb.Clear();

            var lines = KFile.ReadFileLines(file.FullName);

            string newPath = KFile.ReplaceExtension(GetTargetDirFile(file), ".html");

            Flush(newPath);

            var pureName = Path.GetFileNameWithoutExtension(file.Name);
            sb.Append(string.Format(HEADER_TEMPLATE, pureName));

            foreach (var i in lines) {
                sb.Append(string.Format("<p>{0}</p>\n", i));
            }

            sb.Append(FOOT_TEMPLATE);

            File.WriteAllText(newPath, sb.ToString(), Encoding.UTF8);

            content.Append(string.Format(CONTENT_TEMPLATE, pureName, TargetDir));
        }
    }
}
